'''
    This is a tool for sending and receiving AT commands.
    Author: numax;
    Usage: atcsend 'AT+CPIN?''
    Usage: atcsend 'AT+CGDCONT=1,"IP","CMNET"'
'''

#!/usr/bin/python
import serial
import os
import time
import sys
import re

CYCT_MIN_RXBUF_SIZE=128
CYCT_DEF_RXBUF_SIZE=1024
CYCT_MAX_RXBUF_SIZE=4096

CYCT_MIN_TRYWRITE_TIMES=1
CYCT_DEF_TRYWRITE_TIMES=10
CYCT_MAX_TRYWRITE_TIMES=100

CYCT_MIN_TRYREAD_TIMES=5
CYCT_DEF_TRYREAD_TIMES=50
CYCT_MAX_TRYREAD_TIMES=500


gp_tty_dev = "COM6"
gi_tty_speed = 115200

def cyct_tty_open(p_tty_dev):
    p_tty_ctxt = serial.Serial(p_tty_dev, gi_tty_speed, timeout=0.01)
    return p_tty_ctxt

def cyct_tty_write(p_tty_ctxt,p_atc_req):
    i_len_write = 0

    i_len_write = len(p_atc_req)
    p_tty_ctxt.write(p_atc_req)

    return i_len_write

def cyct_tty_read(p_tty_ctxt,i_len_tryread):
    p_cur_read = p_tty_ctxt.read(i_len_tryread)
    return p_cur_read

def cyct_tty_rxclean(p_tty_ctxt):
    i_len_read = 0
    p_cur_read = ""
    p_all_read = ""

    p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
    i_len_read = len(p_cur_read)
    while i_len_read > 0:
        p_all_read = p_all_read + p_cur_read
        p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
        i_len_read = len(p_cur_read)

    return p_all_read

def cyct_tty_close(p_tty_ctxt):
    p_tty_ctxt.close()
    return 1

def cyct_time_tickget():
    i_cnt_curticks = -1

    try:
        i_cnt_curticks = time.time()
        i_cnt_curticks = int(round(i_cnt_curticks * 1000))
    except:
        return i_cnt_curticks

    return i_cnt_curticks

def cyct_prompt_print(p_ascii_string, i_len_record):
    i_len_string = 0
    p_log_string = "NULL"

    i_len_string = len(p_ascii_string)
    if i_len_string <= 0:
        return i_len_string

    p_log_string = p_ascii_string
    if i_len_record > 0:
        p_log_string = p_log_string[0:i_len_record]

    p_log_string = p_log_string.rstrip()
    p_log_string = p_log_string.lstrip()
    i_len_string = len(p_log_string)
    if i_len_string > 0:
        print p_ascii_string

    return i_len_string

def cyct_atcmd_string_wait1(p_tty_ctxt,p_ascii_string1,i_wait_milliseconds):
    i_err_code = 0
    i_len_read = 0
    p_cur_read = ""
    p_all_read = ""
    i_cnt_bticks = 0
    i_cnt_eticks = 0
    i_cnt_cticks = 0

    p_3gpp_error1 = "ERROR:"
    p_3gpp_error2 = "\r\nERROR\r\n"

    i_cnt_cticks = cyct_time_tickget()
    i_cnt_bticks = i_cnt_cticks
    i_cnt_eticks = i_cnt_bticks + i_wait_milliseconds

    '''Get expected response or error'''
    p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
    p_all_read = p_cur_read
    while i_cnt_cticks < i_cnt_eticks:
        if p_ascii_string1 in p_all_read:
            i_err_code = 1
            break
        if p_3gpp_error1 in p_all_read:
            i_err_code = -1
            break
        if p_3gpp_error2 in p_all_read:
            i_err_code = -2
            break
        p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
        p_all_read = p_all_read + p_cur_read
        i_cnt_cticks = cyct_time_tickget()

    '''Get the end of response or URC string'''
    p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
    i_len_read = len(p_cur_read)
    while i_len_read > 0:
        p_all_read = p_all_read + p_cur_read
        p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
        i_len_read = len(p_cur_read)

    return i_err_code, p_all_read

if __name__ == "__main__":
    p_tty_ctxt = "CYCT"
    p_tty_dev = 'COM' + sys.argv[1]
    p_cur_atcmd = sys.argv[2] + '\r'

    i_len_read = 0
    p_cur_read = ""
    p_all_read = ""

    p_tty_ctxt = cyct_tty_open(p_tty_dev)

    p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
    i_len_read = len(p_cur_read)
    while i_len_read > 0:
        p_all_read = p_all_read + p_cur_read
        p_cur_read = cyct_tty_read(p_tty_ctxt,CYCT_MIN_RXBUF_SIZE)
        i_len_read = len(p_cur_read)
    cyct_prompt_print(p_all_read, 0)

    cyct_tty_write(p_tty_ctxt, p_cur_atcmd)
    i_err_code, p_all_wait = cyct_atcmd_string_wait1(p_tty_ctxt, "\r\nOK\r\n", 5000)
    cyct_prompt_print(p_all_wait, 0)

    cyct_tty_close(p_tty_ctxt)

